from django.db import models
from django.contrib.auth import get_user_model
from cryptography.fernet import Fernet
from django.conf import settings
import json

User = get_user_model()


class Environment(models.Model):
    """环境模型"""
    name = models.CharField(max_length=100, verbose_name='环境名称')
    code = models.CharField(max_length=50, unique=True, verbose_name='环境代码')
    description = models.TextField(blank=True, null=True, verbose_name='描述')
    color = models.CharField(max_length=20, default='#409EFF', verbose_name='颜色')
    is_active = models.BooleanField(default=True, verbose_name='是否激活')
    created_at = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
    updated_at = models.DateTimeField(auto_now=True, verbose_name='更新时间')

    class Meta:
        db_table = 'cmdb_environment'
        verbose_name = '环境'
        verbose_name_plural = '环境'
        ordering = ['code']

    def __str__(self):
        return self.name


class HostType(models.Model):
    """主机类型模型"""
    name = models.CharField(max_length=100, verbose_name='类型名称')
    code = models.CharField(max_length=50, unique=True, verbose_name='类型代码')
    icon = models.CharField(max_length=50, default='Monitor', verbose_name='图标')
    color = models.CharField(max_length=20, default='#409EFF', verbose_name='颜色')
    description = models.TextField(blank=True, null=True, verbose_name='描述')

    # 默认规格配置
    default_cpu = models.IntegerField(default=2, verbose_name='默认CPU核数')
    default_memory = models.IntegerField(default=4, verbose_name='默认内存(GB)')
    default_disk = models.IntegerField(default=100, verbose_name='默认磁盘(GB)')

    is_active = models.BooleanField(default=True, verbose_name='是否激活')
    created_at = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
    updated_at = models.DateTimeField(auto_now=True, verbose_name='更新时间')

    class Meta:
        db_table = 'cmdb_host_type'
        verbose_name = '主机类型'
        verbose_name_plural = '主机类型'
        ordering = ['code']

    def __str__(self):
        return self.name

    @property
    def host_count(self):
        """关联的主机数量"""
        return self.hosts.filter(is_active=True).count()


class HostGroup(models.Model):
    """主机组模型"""
    name = models.CharField(max_length=100, verbose_name='组名称')
    code = models.CharField(max_length=50, unique=True, verbose_name='组代码')
    environment = models.ForeignKey(Environment, on_delete=models.CASCADE, verbose_name='环境')
    type = models.CharField(max_length=50, verbose_name='组类型', choices=[
        ('web', 'Web服务器'),
        ('database', '数据库'),
        ('cache', '缓存'),
        ('mq', '消息队列'),
        ('storage', '存储'),
        ('other', '其他')
    ])
    description = models.TextField(blank=True, null=True, verbose_name='描述')

    # 负载均衡配置
    load_balancer_enabled = models.BooleanField(default=False, verbose_name='启用负载均衡')
    load_balancer_algorithm = models.CharField(max_length=50, default='round_robin', verbose_name='负载均衡算法')
    load_balancer_port = models.IntegerField(default=80, verbose_name='负载均衡端口')

    # 健康检查配置
    health_check_enabled = models.BooleanField(default=False, verbose_name='启用健康检查')
    health_check_interval = models.IntegerField(default=30, verbose_name='检查间隔(秒)')
    health_check_timeout = models.IntegerField(default=5, verbose_name='超时时间(秒)')
    health_check_failure_threshold = models.IntegerField(default=3, verbose_name='失败阈值')
    health_check_path = models.CharField(max_length=200, default='/health', verbose_name='检查路径')

    status = models.CharField(max_length=20, default='normal', verbose_name='状态', choices=[
        ('normal', '正常'),
        ('maintenance', '维护中'),
        ('error', '异常')
    ])
    is_active = models.BooleanField(default=True, verbose_name='是否激活')
    created_at = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
    updated_at = models.DateTimeField(auto_now=True, verbose_name='更新时间')

    class Meta:
        db_table = 'cmdb_host_group'
        verbose_name = '主机组'
        verbose_name_plural = '主机组'
        ordering = ['code']

    def __str__(self):
        return self.name

    @property
    def host_count(self):
        """关联的主机数量"""
        return self.hosts.filter(is_active=True).count()


class Host(models.Model):
    """主机模型"""
    hostname = models.CharField(max_length=100, verbose_name='主机名')
    ip = models.GenericIPAddressField(verbose_name='IP地址', db_index=True)
    host_type = models.ForeignKey(HostType, on_delete=models.CASCADE, related_name='hosts', verbose_name='主机类型')
    environment = models.ForeignKey(Environment, on_delete=models.CASCADE, verbose_name='环境')
    host_group = models.ForeignKey(HostGroup, on_delete=models.SET_NULL, null=True, blank=True,
                                   related_name='hosts', verbose_name='主机组')

    # 系统信息
    os = models.CharField(max_length=100, blank=True, null=True, verbose_name='操作系统')
    os_version = models.CharField(max_length=50, blank=True, null=True, verbose_name='系统版本')
    kernel_version = models.CharField(max_length=100, blank=True, null=True, verbose_name='内核版本')

    # 硬件配置
    cpu_cores = models.IntegerField(default=2, verbose_name='CPU核数')
    memory_gb = models.IntegerField(default=4, verbose_name='内存(GB)')
    disk_gb = models.IntegerField(default=100, verbose_name='磁盘(GB)')

    # SSH连接配置
    ssh_port = models.IntegerField(default=22, verbose_name='SSH端口')
    ssh_username = models.CharField(max_length=50, default='root', verbose_name='SSH用户名')
    ssh_auth_type = models.CharField(max_length=20, default='password', verbose_name='认证方式', choices=[
        ('password', '密码认证'),
        ('key', '密钥认证')
    ])
    ssh_password = models.TextField(blank=True, null=True, verbose_name='SSH密码(加密存储)')
    ssh_private_key = models.TextField(blank=True, null=True, verbose_name='SSH私钥(加密存储)')

    # 状态信息
    status = models.CharField(max_length=20, default='unknown', verbose_name='状态', choices=[
        ('online', '在线'),
        ('offline', '离线'),
        ('maintenance', '维护中'),
        ('error', '故障')
    ])
    last_heartbeat = models.DateTimeField(null=True, blank=True, verbose_name='最后心跳时间')

    # 监控配置
    monitor_enabled = models.BooleanField(default=True, verbose_name='启用监控')
    monitor_interval = models.IntegerField(default=30, verbose_name='监控间隔(秒)')

    # 标签和描述
    tags = models.JSONField(default=list, blank=True, verbose_name='标签')
    description = models.TextField(blank=True, null=True, verbose_name='描述')

    # 管理信息
    owner = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True, verbose_name='负责人')
    is_active = models.BooleanField(default=True, verbose_name='是否激活')
    created_at = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
    updated_at = models.DateTimeField(auto_now=True, verbose_name='更新时间')

    class Meta:
        db_table = 'cmdb_host'
        verbose_name = '主机'
        verbose_name_plural = '主机'
        ordering = ['-created_at']
        unique_together = ['hostname', 'environment']

    def __str__(self):
        return f"{self.hostname} ({self.ip})"

    def encrypt_password(self, password):
        """加密密码"""
        if not password:
            return None
        from common.security import encryption_manager
        return encryption_manager.encrypt(password)

    def decrypt_password(self):
        """解密SSH密码"""
        if self.ssh_password:
            try:
                from common.security import encryption_manager
                return encryption_manager.decrypt(self.ssh_password)
            except Exception:
                # 如果解密失败，可能是未加密的数据，尝试使用旧方法
                try:
                    key = getattr(settings, 'ENCRYPTION_KEY', None)
                    if key:
                        f = Fernet(key)
                        return f.decrypt(self.ssh_password.encode()).decode()
                except Exception:
                    pass
                # 最后返回原始值
                return self.ssh_password
        return None

    def encrypt_private_key(self, private_key):
        """加密私钥"""
        if not private_key:
            return None
        from common.security import encryption_manager, security_validator
        # 验证私钥格式
        if not security_validator.validate_ssh_key(private_key):
            raise ValueError("无效的SSH私钥格式")
        return encryption_manager.encrypt(private_key)

    def decrypt_private_key(self):
        """解密SSH私钥"""
        if self.ssh_private_key:
            try:
                from common.security import encryption_manager
                return encryption_manager.decrypt(self.ssh_private_key)
            except Exception:
                # 如果解密失败，可能是未加密的数据，尝试使用旧方法
                try:
                    key = getattr(settings, 'ENCRYPTION_KEY', None)
                    if key:
                        f = Fernet(key)
                        return f.decrypt(self.ssh_private_key.encode()).decode()
                except Exception:
                    pass
                # 最后返回原始值
                return self.ssh_private_key
        return None

    def set_ssh_password(self, password):
        """设置并加密SSH密码"""
        if password:
            self.ssh_password = self.encrypt_password(password)
        else:
            self.ssh_password = None

    def set_ssh_private_key(self, private_key):
        """设置并加密SSH私钥"""
        if private_key:
            self.ssh_private_key = self.encrypt_private_key(private_key)
        else:
            self.ssh_private_key = None

    @property
    def is_online(self):
        """是否在线"""
        return self.status == 'online'

    @property
    def connection_info(self):
        """获取连接信息"""
        return {
            'hostname': self.hostname,
            'ip': self.ip,
            'port': self.ssh_port,
            'username': self.ssh_username,
            'auth_type': self.ssh_auth_type
        }
